/*
 * Sylvain BERTRAND <digital.ragnarok@gmail.com>
 * code protected by GNU GPL v3
 */
#include <stdlib.h>
#include <X11/Xlib.h>
#include <glib.h>
#include "../nls.h"
#include "../toolkit/keyboard.h"
#include "../toolkit/display.h"
static guint translate_modifier(gchar *str)
{
	guint mask = 0;
	if(!g_ascii_strcasecmp("Mod1", str))
		mask = Mod1Mask;
	else if(!g_ascii_strcasecmp("Mod2", str))
		mask = Mod2Mask;
	else if(!g_ascii_strcasecmp("Mod3", str))
		mask = Mod3Mask;
	else if(!g_ascii_strcasecmp("Mod4", str))
		mask = Mod4Mask;
	else if(!g_ascii_strcasecmp("Mod5", str))
		mask = Mod5Mask;
	else if(!g_ascii_strcasecmp("Control", str) || !g_ascii_strcasecmp("C", str))
		mask = t_keyboard_modkey_to_modmask(T_KEYBOARD_MODKEY_CONTROL);
	else if(!g_ascii_strcasecmp("Alt", str) || !g_ascii_strcasecmp("A", str))
		mask = t_keyboard_modkey_to_modmask(T_KEYBOARD_MODKEY_ALT);
	else if(!g_ascii_strcasecmp("Meta", str) || !g_ascii_strcasecmp("M", str))
		mask = t_keyboard_modkey_to_modmask(T_KEYBOARD_MODKEY_META);
	else if(!g_ascii_strcasecmp("Super", str) || !g_ascii_strcasecmp("W", str))
		mask = t_keyboard_modkey_to_modmask(T_KEYBOARD_MODKEY_SUPER);
	else if(!g_ascii_strcasecmp("Shift", str) || !g_ascii_strcasecmp("S", str))
		mask = t_keyboard_modkey_to_modmask(T_KEYBOARD_MODKEY_SHIFT);
	else if(!g_ascii_strcasecmp("Hyper", str) || !g_ascii_strcasecmp("H", str))
		mask = t_keyboard_modkey_to_modmask(T_KEYBOARD_MODKEY_HYPER);
	else
		g_message(_("Invalid modifier key \"%s\" in key/mouse binding"), str);
	return mask;
}

gboolean translate_button(const gchar *str, guint *state, guint *button)
{
	gchar **parsed;
	gchar *l;
	gint i;
	gboolean ret = FALSE;
	parsed = g_strsplit(str, "-", -1);
	l = NULL;
	for(i = 0; parsed[i] != NULL; ++i)
		l = parsed[i];
	if(l == NULL)
		goto translation_fail;
	*state = 0;
	for(i = 0; parsed[i] != l; ++i) {
		guint m = translate_modifier(parsed[i]);
		if(!m)
			goto translation_fail;
		*state |= m;
	}
	if(!g_ascii_strcasecmp("Left", l))
		*button = 1;
	else if(!g_ascii_strcasecmp("Middle", l))
		*button = 2;
	else if(!g_ascii_strcasecmp("Right", l))
		*button = 3;
	else if(!g_ascii_strcasecmp("Up", l))
		*button = 4;
	else if(!g_ascii_strcasecmp("Down", l))
		*button = 5;
	else if(!g_ascii_strncasecmp("Button", l, 6))
		*button = atoi(l + 6);
	if(!*button)
		goto translation_fail;
	ret = TRUE;
translation_fail:
	g_strfreev(parsed);
	return ret;
}

gboolean translate_key(const gchar *str, guint *state, guint *keycode)
{
	gchar **parsed;
	gchar *l;
	gint i;
	gboolean ret = FALSE;
	KeySym sym;
	parsed = g_strsplit(str, "-", -1);
	*state = *keycode = 0;
	l = NULL;
	for(i = 0; parsed[i] != NULL; ++i)
		l = parsed[i];
	if(l == NULL)
		goto translation_fail;
	*state = 0;
	for(i = 0; parsed[i] != l; ++i) {
		guint m = translate_modifier(parsed[i]);
		if(!m)
			goto translation_fail;
		*state |= m;
	}
	if(!g_ascii_strncasecmp("0x", l, 2)) {
		gchar *end;
		*keycode = strtol(l, &end, 16);
		if(*l == '\0' || *end != '\0') {
			g_message(_("Invalid key code \"%s\" in key binding"), l);
			goto translation_fail;
		}
	} else {
		sym = XStringToKeysym(l);
		if(sym == NoSymbol) {
			g_message(_("Invalid key name \"%s\" in key binding"), l);
			goto translation_fail;
		}
		*keycode = XKeysymToKeycode(t_display, sym);
	}
	if(!*keycode) {
		g_message(_("Requested key \"%s\" does not exist on the display"), l);
		goto translation_fail;
	}
	ret = TRUE;
translation_fail:
	g_strfreev(parsed);
	return ret;
}
